use crate::config::Config;
use crate::preview::preview_code_with_fallback;
use crate::CodeSnippet;
use std::fs;

use rustyline::DefaultEditor;
use std::process::Command;

// ANSI color codes 🎨
const COLOR_GREEN: &str = "\x1b[32m";
const COLOR_YELLOW: &str = "\x1b[33m";
const COLOR_PURPLE: &str = "\x1b[35m";
const COLOR_MAGENTA: &str = "\x1b[95m";
const COLOR_RESET: &str = "\x1b[0m";
const COLOR_BOLD: &str = "\x1b[1m";
const COLOR_RED: &str = "\x1b[31m";

pub fn execute_snippet(
    snippet: &CodeSnippet,
    config: &Config,
    save: bool,
) -> Result<(), Box<dyn std::error::Error>> {
    // Get language configuration
    let lang_config = config
        .languages
        .get(&snippet.language)
        .ok_or(format!("Unsupported language: {}", snippet.language))?;

    // Create temporary file or saved file
    let (temp_file_path, is_saved_file) = if save {
        // Save mode: create file in current directory
        let current_dir = std::env::current_dir()?;
        let file_name = format!("yk_saved.{}", lang_config.extension);
        let save_path = current_dir.join(file_name);
        (save_path, true)
    } else {
        // Normal mode: create temporary file
        let temp_dir = std::env::temp_dir();
        let file_name = format!("yk_temp.{}", lang_config.extension);
        let temp_path = temp_dir.join(file_name);
        (temp_path, false)
    };

    // Write code to temporary file
    fs::write(&temp_file_path, &snippet.code)?;

    // Build execution command
    let interpreter = &lang_config.interpreter;
    let mut parts = interpreter.split_whitespace();
    let program = parts.next().ok_or("Interpreter configuration error")?;
    let interpreter_args: Vec<&str> = parts.collect(); // Interpreter built-in arguments

    // Display the command to be executed 🚀
    print!(
        "{}{}🚀 Command to be executed{}",
        COLOR_BOLD, COLOR_GREEN, COLOR_RESET
    );
    if !interpreter_args.is_empty() {
        print!(" {} ", interpreter_args.join(" "));
    }
    // Use rustyline to provide interactive command editing 📝
    let mut rl = DefaultEditor::new()?;

    // Build the initial command for user editing
    let mut initial_command = format!("{} {}", program, temp_file_path.display());
    if !interpreter_args.is_empty() {
        initial_command = format!(
            "{} {} {}",
            program,
            interpreter_args.join(" "),
            temp_file_path.display()
        );
    }

    println!(
        "\n{}💭 Edit the command below (Press Enter to execute, Ctrl+C to cancel):{}",
        COLOR_YELLOW, COLOR_RESET
    );

    // Read user input with pre-filled command
    let readline = rl.readline_with_initial("&gt: ", (&initial_command, ""));

    let final_command = match readline {
        Ok(line) => {
            let edited_command = line.trim();
            if !edited_command.is_empty() {
                // Display the complete command after editing 🎬
                println!(
                    "\n{}{}🎬 Final command to execute{}",
                    COLOR_BOLD, COLOR_PURPLE, COLOR_RESET
                );
                println!(
                    "{}═══════════════════════════════════════{}",
                    COLOR_MAGENTA, COLOR_RESET
                );
                print!("{}💻 Complete command:{}", COLOR_YELLOW, COLOR_RESET);
                print!(" {} {}", COLOR_BOLD, edited_command);
                println!();
                println!(
                    "{}═══════════════════════════════════════{}",
                    COLOR_MAGENTA, COLOR_RESET
                );
                edited_command.to_string()
            } else {
                return Ok(());
            }
        }
        Err(rustyline::error::ReadlineError::Interrupted) => {
            println!(
                "\n{}❌ Command execution cancelled by user.{}",
                COLOR_RED, COLOR_RESET
            );
            return Ok(());
        }
        Err(err) => {
            return Err(format!("Error reading input: {}", err).into());
        }
    };

    // Execute code 🎯
    println!(
        "\n{}🎯 Starting command execution...{}",
        COLOR_BOLD, COLOR_RESET
    );

    // Parse and execute the final command
    let cmd_parts: Vec<&str> = final_command.split_whitespace().collect();
    if cmd_parts.is_empty() {
        return Ok(());
    }

    let program = cmd_parts[0];
    let args = &cmd_parts[1..];

    let status = Command::new(program).args(args).status()?;

    // Clean up temporary file only in normal mode
    if !is_saved_file {
        let _ = fs::remove_file(&temp_file_path);
    }

    if !status.success() {
        return Err(format!("Execution failed, exit code: {:?}", status.code()).into());
    }

    // Show save completion message in save mode
    if is_saved_file {
        println!(
            "\n{}✅ Execution completed. File saved at: {}{}",
            COLOR_GREEN,
            COLOR_RESET,
            temp_file_path.display()
        );
    }

    Ok(())
}

pub fn handle_preview_command(file: &str, line: usize) -> Result<(), Box<dyn std::error::Error>> {
    preview_code_with_fallback(file, line, None).map_err(|e| format!("Preview error: {}", e).into())
}

pub fn handle_save_mode(
    _config: &Config,
    _snippets: Vec<crate::CodeSnippet>,
) -> Result<(), Box<dyn std::error::Error>> {
    // This function is now handled directly in main.rs
    // The save mode logic is implemented by calling execute_snippet with save=true
    Ok(())
}
